package com.powerunion.datacollection.common;

import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collection;

import javax.servlet.ServletContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

//import com.powerunion.epms.excel.valid.EValidate;

public class ExcelImportHandler {

	private final static String CONFIG_PATH = "/WEB-INF/sys-config/excel_config.xml";

	private ServletContext context;

	private String configDefinedId;
	
	private String classzz;
	
	private Element element;
	
	private Workbook workbook;
	
	private Sheet sheet;
	
	 private static final Object[] EMPTY_ARGS = new Object[0];
	 
     private static final Class[] EMPTY_PARAM_TYPES = new Class[0];
	
 	public ExcelImportHandler() {
		
	}
     
	public ExcelImportHandler(ServletContext context, String configDefinedId) {
		this(context, configDefinedId, null);
	}
	
	public ExcelImportHandler(ServletContext context, String configDefinedId, InputStream is) {	
		this.context = context;
		this.configDefinedId = configDefinedId;
		initXMLObject(is);
	}
	
	private void initXMLObject(InputStream is) {	
		try {
			InputStream configInputStream = is;
			if(configInputStream == null)
				configInputStream = context.getResourceAsStream(CONFIG_PATH);
			
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			DocumentBuilder db = dbf.newDocumentBuilder();
			Document doc = db.parse(configInputStream);
			NodeList nl = doc.getElementsByTagName("import");
			Element el = null;
			for(int i = 0, n = nl.getLength(); i < n; i++) {
				el = (Element) nl.item(i);
				if(el.getAttribute("id").equals(configDefinedId)) {
					this.element = el;
					this.classzz = el.getAttribute("class");
					break;			
				}
			}
			
			if(element == null) 
				throw new RuntimeException("没有正确的配置导出格式");
			
			configInputStream.close();
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
	
	private void initJXLObject(InputStream excelStream, int sheetIdx) throws Exception {
		try {
			workbook = Workbook.getWorkbook(excelStream);
			sheet = workbook.getSheet(sheetIdx);
		} catch(Exception e) {
			throw e;
		}
	}
	
	private Object createDataObjectInstance() throws Exception {
		try {
	        Class target = Class.forName(classzz);
	        Constructor c = target.getDeclaredConstructor(EMPTY_PARAM_TYPES);
            c.setAccessible( true );
            return c.newInstance( EMPTY_ARGS );
		} catch(Exception e) {
			throw e;
		}
	}
	
	private int getRows() {
		return sheet.getRows();
	}
	
	private int getRowStartIndex(boolean hasHeader) {
		return (hasHeader)? 1: 0;
	}

	private String getData(int cell, int row) {
		Cell cl = this.sheet.getCell(cell, row);
		return cl.getContents();
	}

	public Collection fromExcelStream(InputStream excelStream, int sheetIdx, boolean hasHeader) throws Exception {
		if(excelStream == null)
			throw new NullPointerException("Excel数据为Null");
		
		try {
			if(workbook == null)
				initJXLObject(excelStream, sheetIdx);
			
			NodeList columnNodeList = element.getElementsByTagName("column");
			Collection objects = new ArrayList();
			for (int i = getRowStartIndex(hasHeader), n = this.getRows(); i < n; i++) {
				Object dataObject = createDataObject(i, columnNodeList);
				if(dataObject != null)
				   objects.add(dataObject);
			}
			
			return objects;
			
		} catch(Exception e) {
			throw e;
		} finally {
			if(workbook != null) {
				workbook.close();
			}
		}
	}

	private Object createDataObject(int rowIndex, NodeList columnNodeList) throws Exception {
		int cellIndex = 0;
		boolean allowBlank = true;
		Object dataObject = createDataObjectInstance();
		for(int i = 0, n = columnNodeList.getLength(); i < n; i++) {
			Element el = (Element) columnNodeList.item(i);
			cellIndex = Integer.parseInt(el.getAttribute("index"));
			String allowBlankStr = el.getAttribute("allowBlank");
			allowBlank = (!StringUtils.isBlank(allowBlankStr))? Boolean.valueOf(allowBlankStr).booleanValue(): true;
			if(!allowBlank && StringUtils.isEmpty(getData(cellIndex, rowIndex))) {
				dataObject = null;
				break;
			}
			BeanUtils.setProperty(dataObject,el.getAttribute("property"), getData(cellIndex, rowIndex));
		}
		return dataObject;
	}

//	public Collection validate(InputStream excelStream, int sheetIdx, boolean hasHeader) throws Exception {
//		if(excelStream == null)
//			throw new NullPointerException("Excel数据为Null");
//		try {
//			if(workbook == null)
//				initJXLObject(excelStream, sheetIdx);
//			////ExcelValidate validate = new ExcelValidate(this.sheet,hasHeader,element.getElementsByTagName("column"));
//			//EValidate validate = new EValidate(this.sheet,hasHeader,element.getElementsByTagName("column"));
//			return validate.valid();
//		}catch(Exception e){
//			throw e;
//		}
//	}
}
